package com.embedsky.administrator.mycardemulation.socket;

import android.util.Log;

import com.embedsky.administrator.mycardemulation.util.SafeCloseUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Des:
 * @Author: hang.zhao
 * @Date: 2023/2/26
 */
public class ServerThread extends Thread{
    public static final String TAG = "ServerThread";
    private final IServerListener mServerListener;
    private ServerSocket mServerSocket;
    // socket to be connected
    private ConcurrentHashMap<String, SocketHandler> mSocketMap = new ConcurrentHashMap<>();
    private volatile boolean mRunning;

    public ServerThread(int port, IServerListener listener) {
        mServerListener = listener;
        //SDD modify use dynamic port for NFRFP-4751 by wenhao.fan 20210325 start
        try {
            mServerSocket = new ServerSocket(port);
            mServerSocket.setReuseAddress(true);
            mServerListener.onServerStart(port);
            mRunning = true;
            start();
        } catch (IOException e) {
            mServerListener.onServerStartErr(port);
            e.printStackTrace();
        }
        //SDD modify use dynamic port for NFRFP-4751 by wenhao.fan 20210325 end
    }

    @Override
    public void run() {
        while (mRunning) {
            try {
                Socket socket = mServerSocket.accept();
                InetSocketAddress remoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
                String ip = remoteSocketAddress.getAddress().getHostAddress();
                SocketHandler handler = mSocketMap.get(ip);
                if (null != handler) {
                    handler.finish();
                }
                SocketHandler socketHandler = new SocketHandler(socket, ip) {
                    @Override
                    public void parseData(byte[] bytes, String srcIp) {
                        mServerListener.parseData(bytes, srcIp);
                    }

                    @Override
                    public void disconnect(String srcIp) {
                        mServerListener.onClientDisconnect(srcIp);
                        //SDD: modify for LEQHLJQ-1370 by linhui.shi 20210512 start
                        mSocketMap.remove(srcIp);
                        //SDD: modify for LEQHLJQ-1370 by linhui.shi 20210512 end
                    }

                    @Override
                    protected void onBeatBreak(String srcIp) {
                        Log.d(TAG, "onBeatBreak: ");
                        mServerListener.onClientDisconnect(srcIp);
                        //SDD: modify for LEQHLJQ-1370 by linhui.shi 20210512 start
                        mSocketMap.remove(srcIp);
                        //SDD: modify for LEQHLJQ-1370 by linhui.shi 20210512 end
                    }
                };
                mSocketMap.put(ip, socketHandler);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @return null
     * @Des: finish the server,after send finish cmd to all connected clients;
     */
    public void finish() {
        Log.d(TAG, "finish: ");
        if (!mSocketMap.isEmpty()) {
            for (SocketHandler socketHandler : mSocketMap.values()) {
                socketHandler.finish();
            }
            mSocketMap.clear();
        }
        mRunning = false;
        SafeCloseUtil.close(mServerSocket);
        mServerListener.onFinish();
    }

    public void sendData(String data, String ip) {
        Log.d(TAG, "sendData: " + data);
        SocketHandler socketHandler = mSocketMap.get(ip);
        if (null != socketHandler) {
            socketHandler.putOutMessage(data.getBytes(Charset.defaultCharset()));
        }
    }

    public void broadcastData(String data) {
        if (!mSocketMap.isEmpty()) {
            Log.d(TAG, "broadcastData: " + data);
            for (SocketHandler handler : mSocketMap.values()) {
                handler.putOutMessage(data.getBytes(Charset.defaultCharset()));
            }
        }
    }

    public void closeClient(String ip) {
        SocketHandler socketHandler = mSocketMap.get(ip);
        if (null != socketHandler) {
            socketHandler.finish();
        }
        //SDD: modify for LEQHLJQ-1370 by linhui.shi 20210512 start
        mSocketMap.remove(ip);
        //SDD: modify for LEQHLJQ-1370 by linhui.shi 20210512 end
    }

}
